package com.zlzlib.libui.weight.slidmenu;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.RelativeLayout;

import com.zlzlib.libui.util.ViewClickDelay;

/**
 * @Desc: 一个双向滑动的菜单控件
 * @Copyright:
 * @DateTime: 2020/11/3 15:24
 * @Author zlz
 * @Version 1.0
 */
public class TowSideView extends RelativeLayout {


    /**
     * 定义内容子控
     */
    private View slideLeftView, slideMainView, slideRightView;
    /**
     * 定义一个中间层的挡板遮罩层
     */
    private View mainMaskView;
    /**
     * 遮罩层颜色
     */
    private final int maskColor;
    // 左右使用宽带 ，左右真实宽度
    private int leftViewW, rightViewW, leftRelView, rightRelView;

    /**
     * 屏幕宽度
     */
    private final int mScreenWidth;
    /**
     * 锁定滑动 ,锁定右和左
     */
    private boolean isLockScroll = false, isCanLeft = true, isCanRight = true;
    // 正在滑动
    private boolean isScrolling = false;
    // 第一次加载
    private boolean once = false, first = false;
    // 当前滑动的数据 总滑动的数据 按下的坐标，当此移动的距离 滑动系数
    private float xTotalMove, xDown, yDown, xLastMove, xMove, xScroll = 1f;

    private final int TYPE_LEFT = 0, TYPE_MAIN = 1, TYPE_RIGHT = 2;
    /**
     * 当前滑动的状态
     */
    private int slideType = TYPE_MAIN;
    private ScrollListener scrollListener;
    private ScrollSelectListener scrollSelectListener;

    public TowSideView(Context context) {
        this(context, null);
    }

    public TowSideView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TowSideView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(metrics);
        mScreenWidth = metrics.widthPixels;
        maskColor = Color.parseColor("#66333333");
        xTotalMove = 0;
        speed = (int) ((context.getResources().getDisplayMetrics().density * 11) + 0.5f);
    }

    /**
     * 当布局xml加载完成后，就会调用此方法，然后此方法再去获取子控件View
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        try {
            // 获取子控件View
            if (getChildCount() < 1) {
                return;
            }
            slideMainView = getChildAt(getChildCount() - 1);
            if (getChildCount() > 1) {
                slideRightView = getChildAt(getChildCount() - 2);
            }
            if (getChildCount() > 2) {
                slideLeftView = getChildAt(getChildCount() - 3);
            }
            mainMaskView = new View(getContext());
            mainMaskView.setBackgroundColor(maskColor);
            ViewGroup.LayoutParams params = slideMainView.getLayoutParams();
            addView(mainMaskView, params);
            mainMaskView.setVisibility(GONE);
            ViewClickDelay.addClick(mainMaskView, v -> slideMain());
        } catch (Exception ignored) {
        }
    }

    /**
     * 设置子View的宽和高 设置自己的宽和高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (!once) {
            // 主页面与屏幕一样大
            if (null != slideMainView) {
                slideMainView.getLayoutParams().width = mScreenWidth;
                mainMaskView.getLayoutParams().width = mScreenWidth;
            }
            once = true;
        }
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        // 获得左右宽度
        if (null != slideLeftView) {
            leftRelView = slideLeftView.getMeasuredWidth();
        }
        if (null != slideRightView) {
            rightRelView = slideRightView.getMeasuredWidth();
        }
        if (!first) {
            first = true;
            scrollChild(0);
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (isScrolling) {
            return super.onInterceptTouchEvent(ev);
        }
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 手指按下时，记录按下时的坐标
                xDown = ev.getX();
                yDown = ev.getY();
                leftViewW = isCanLeft ? leftRelView : 0;
                rightViewW = isCanRight ? rightRelView : 0;
                xLastMove = ev.getX();
                break;
            case MotionEvent.ACTION_MOVE:
                float dx = Math.abs(ev.getX() - xDown);
                float dy = Math.abs(ev.getY() - yDown);
                if (dx > dy) {
                    return true;
                } else {
                    return super.onInterceptTouchEvent(ev);
                }
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (isLockScroll || isScrolling) {
            return super.onTouchEvent(ev);
        }
        int action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                leftViewW = isCanLeft ? leftRelView : 0;
                rightViewW = isCanRight ? rightRelView : 0;
                xLastMove = ev.getX();
                return true;
            case MotionEvent.ACTION_MOVE:
                xMove = ev.getX();
                // 手指移动时，对比按下时的坐标，计算出移动的距离。
                float moveDistanceX = xMove - xLastMove;
                xLastMove = xMove;
                xTotalMove += (moveDistanceX * xScroll);
                // 边界计算
                if (xTotalMove > leftViewW) {
                    xTotalMove = leftViewW;
                }
                if (xTotalMove < -rightViewW) {
                    xTotalMove = -rightViewW;
                }
                // 开始滑动
                scrollChild((int) xTotalMove);
                return true;
            case MotionEvent.ACTION_UP:
                // 如果滑动大于 左边的一半
                if (xTotalMove > leftViewW / 2) {
                    // slideLeftView 显示出来
                    toLeft();
                } else if (xTotalMove < -rightViewW / 2) {
                    // 如果滑动大于 右边的一半
                    // slideRightView 显示出来
                    toRight();
                } else {
                    // 初始状态
                    toMain();
                }
                return super.onTouchEvent(ev);
        }
        return super.onTouchEvent(ev);
    }

    private void scrollChild(int move) {
        // 边界判断
        if (move > leftRelView) {
            move = leftRelView;
        }
        if (move < -rightRelView) {
            move = -rightRelView;
        }
        xTotalMove = move;
        if (slideMainView != null) {
            slideMainView.setTranslationX(move);
        }
        if (mainMaskView != null) {
            mainMaskView.setTranslationX(move);
        }
        if (slideLeftView != null) {
            slideLeftView.setTranslationX(-leftRelView + move);
        }
        if (slideRightView != null) {
            slideRightView.setTranslationX(mScreenWidth + move);
        }
    }

    private void toLeft() {
        slideType = TYPE_LEFT;
        myScroll(leftRelView, 0);
    }

    private void toRight() {
        slideType = TYPE_RIGHT;
        myScroll(-rightRelView, 0);
    }

    private void toMain() {
        slideType = TYPE_MAIN;
        myScroll(0, 0);
    }

    /**
     * 每个时间单位移动的距离
     */
    private int speed = 15;
    /**
     * 当前处于的位置
     */
    private int curX = 0;

    /**
     * 滑动完成给个监听
     *
     * @param x
     * @param y
     */
    private void myScroll(final int x, final int y) {
        curX = (int) (xTotalMove);
        final Timer timer = new Timer();
        isScrolling = true;
        TimerTask task = new TimerTask() {

            @Override
            public void run() {
                if (curX == x) {
                    taskScrollFinish(timer, x, y);
                    return;
                }
                if (curX > x) {
                    curX -= speed;
                    if (curX < x) {
                        taskScrollFinish(timer, x, y);
                        return;
                    }
                } else {
                    curX += speed;
                    if (curX > x) {
                        taskScrollFinish(timer, x, y);
                        return;
                    }
                }
                postScrollTo(curX, y);
            }
        };
        timer.schedule(task, 0, 8);
    }

    private void taskScrollFinish(Timer timer, final int x, final int y) {
        timer.cancel();
        isScrolling = false;
        post(new Runnable() {

            @Override
            public void run() {
                scrollChild(x);
                if (null != mainMaskView) {
                    switch (slideType) {
                        case TYPE_LEFT:
                        case TYPE_RIGHT:
                            mainMaskView.setVisibility(VISIBLE);
                            break;
                        default:
                            mainMaskView.setVisibility(GONE);
                            break;
                    }
                }
                if (null != scrollListener) {
                    scrollListener.scrollFinish();
                }
                if (null != scrollSelectListener) {
                    if (slideType == TYPE_LEFT) {
                        scrollSelectListener.left();
                    } else if (slideType == TYPE_RIGHT) {
                        scrollSelectListener.right();
                    } else if (slideType == TYPE_MAIN) {
                        scrollSelectListener.main();
                    }
                }
            }
        });
    }

    private void postScrollTo(final int x, final int y) {
        post(new Runnable() {

            @Override
            public void run() {
                scrollChild(x);
            }
        });
    }

//	private void log(String s) {
//		System.err.println(getClass().getName() + " : " + s);
//	}

    /**
     * 向右滑出菜单显示出来
     */
    public void slideOutLeftMenu() {
        if (slideType != TYPE_LEFT && !isScrolling) {
            toLeft();
        }
    }

    /**
     * 向左滑出菜单显示出来
     */
    public void slideOutRightMenu() {
        if (slideType != TYPE_RIGHT && !isScrolling) {
            toRight();
        }
    }

    /**
     * 滑到中间
     */
    public void slideMain() {
        if (slideType != TYPE_MAIN && !isScrolling) {
            toMain();
        }
    }

    public boolean isLockScroll() {
        return isLockScroll;
    }

    public void setLockScroll(boolean lockScroll) {
        isLockScroll = lockScroll;
    }

    public boolean isCanLeft() {
        return isCanLeft;
    }

    public void setCanLeft(boolean isCanLeft) {
        this.isCanLeft = isCanLeft;
    }

    public boolean isCanRight() {
        return isCanRight;
    }

    public void setCanRight(boolean isCanRight) {
        this.isCanRight = isCanRight;
    }

    public void setScrollListener(ScrollListener scrollListener) {
        this.scrollListener = scrollListener;
    }

    public void setScrollSelectListener(ScrollSelectListener scrollSelectListener) {
        this.scrollSelectListener = scrollSelectListener;
    }

    public interface ScrollListener {

        void scrollFinish();

    }

    public interface ScrollSelectListener {

        void left();

        void main();

        void right();

    }

}
